package drds.common.db.sql_mapping;

import drds.common.$;
import drds.common.ClassSearcher;
import drds.common.Constants;
import drds.common.db.sql_mapping.annotation.dto.Dto;
import drds.common.db.sql_mapping.annotation.dto.DtoMapping;
import drds.common.db.sql_mapping.annotation.mapper_class.Database;
import drds.common.db.sql_mapping.annotation.mapper_class.DatabaseId;
import drds.common.db.sql_mapping.configuration.Configuration;
import drds.common.db.sql_mapping.configuration.DtocClassToDtoMappingMap;
import drds.common.db.sql_mapping.configuration.MapperDatabaseIdToConfigurationMap;
import drds.common.db.sql_mapping.configuration.XmlMappersBuilder;
import drds.common.db.sql_mapping.sql_execute.MapperExecutionContext;
import drds.common.db.sql_mapping.sql_execute.MapperExecutionContextImpl;
import drds.config.test.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class Mapper {
    public static UserMapper getMapper(Class clazz) throws IllegalAccessException {

        dtoClassScan();
        mapperScan();
        //
        String mapperDatabaseId = MapperDatabaseIdToConfigurationMap.MapperClassToDatabaseIdMap.get(clazz);
        if ($.isNullOrEmpty(mapperDatabaseId)) {
            throw new NullPointerException("mapperDatabaseId");
        }
        Configuration configuration = MapperDatabaseIdToConfigurationMap.DatabaseIdToConfigurationMap.get(mapperDatabaseId);
        MapperExecutionContext mapperExecutionContext = new MapperExecutionContextImpl(configuration);
        return mapperExecutionContext.getMapper(UserMapper.class);
    }

    /**
     * dto/入参和出参配置
     */
    public static void dtoClassScan() throws IllegalAccessException {
        String basePackage = DtocClassToDtoMappingMap.class.getName().split("\\.")[0];
        List<Class> classList = ClassSearcher.findAnnotationClass(Dto.class, basePackage);
        if (!$.isNotNullAndHasElement(classList)) {
            System.out.println("没有注解标识的类");
            return;
        }

        for (Class clazz : classList) {
            DtoMapping dtoMapping = new DtoMapping(clazz);
            //这个是最原始的DTO信息注册
            //在xml中可以对这部分进行重写,两者共用相关的dto类
            dtoMapping.buildFeildToColumnMapping();
            DtocClassToDtoMappingMap.classToDtoMappingMap.put(clazz, dtoMapping);
            //

        }
    }

    //
    public static void mapperScan() throws IllegalAccessException {
        /**
         * 该数据库交互框架只是为drds服务,故代码写成这样。
         */
        String basePackage = $.rootPackageName;
        List<Class> classList = ClassSearcher.findImplementionClass(Database.class, basePackage);
        if (!$.isNotNullAndHasElement(classList)) {
            System.out.println("没有注解标识的类");
            return;
        }
        Map<String, String> mapperDatabaseIdToPackageNameMap = new HashMap<String, String>();
        for (Class clazz : classList) {
            DatabaseId databaseId = (DatabaseId) clazz.getAnnotation(DatabaseId.class);
            String format = String.format("请标记是哪个组数据库(%s)", clazz);
            if (databaseId == null) {
                throw new IllegalStateException(format);
            }
            if (databaseId.databaseId() == null) {
                throw new IllegalStateException(format);
            }
            mapperDatabaseIdToPackageNameMap.put(databaseId.databaseId(), clazz.getPackage().getName());
            //在组数据库里面检查是否存在
            format = String.format("包%s标记为%s组数据库", clazz.getPackage().getName(), databaseId.databaseId());
            log.info(format);
        }
        //
        for (Map.Entry entry : mapperDatabaseIdToPackageNameMap.entrySet()) {
            String mapperDatabaseId = (String) entry.getKey();
            String packageName = (String) entry.getValue();
            //
            doMapperScan(mapperDatabaseId, packageName);
        }
    }

    private static void doMapperScan(String mapperDatabaseId, String basePackage) {
        List<Class> classList = ClassSearcher.findAnnotationClass(drds.common.db.sql_mapping.annotation.mapper_class.Mapper.class, basePackage);
        if (!$.isNotNullAndHasElement(classList)) {
            System.out.println("没有注解标识的类");
            return;
        }
        MapperDatabaseIdToConfigurationMap.DatabaseIdToConfigurationMap.putIfAbsent(mapperDatabaseId, new Configuration());
        Configuration configuration = MapperDatabaseIdToConfigurationMap.DatabaseIdToConfigurationMap.get(mapperDatabaseId);
        for (Class clazz : classList) {
            configuration.addMapperInterfaceClass(clazz);
            MapperDatabaseIdToConfigurationMap.MapperClassToDatabaseIdMap.put(clazz, mapperDatabaseId);
        }
        mapperElement(configuration, classList);
    }

    private static void mapperElement(Configuration configuration, List<Class> classList) {
        if ($.isNotNullAndHasElement(classList)) {
            for (Class clazz : classList) {
                {
                    String classFullClassName = clazz.getName();
                    if (Constants.developMode) {
                        log.debug("对类:" + classFullClassName + "对应的xml mapper文件进行解析");
                    }
                    String path = "xml/" + clazz.getSimpleName() + ".xml";
                    InputStream inputStream = clazz.getResourceAsStream(path);
                    XmlMappersBuilder xmlMappersBuilder = new XmlMappersBuilder(inputStream, configuration, classFullClassName);
                    xmlMappersBuilder.parse();
                }
            }
        }
    }
}
